/**
 * 210526：新版本射线阈值设置
 */
let THREE=require('three');
import SelectConfig from "./select-config";
import GeometryUtils from "../general/geometry-utils";
import HardLine from "../graphic/hard-line";

/**
 * 投影几何体
 */
class SelectGeometry{
    constructor(){
        this.vertices=null;
        this.lines=null;
        this.maxX=Number.NEGATIVE_INFINITY;
        this.maxY=Number.NEGATIVE_INFINITY;
        this.minX=Number.POSITIVE_INFINITY;
        this.minY=Number.POSITIVE_INFINITY;
    }

    /**
     * 设置等点序列长度
     * @param length
     */
    set vCount(length){
        this.vertices=new Float32Array(length);
    }

    /**
     * 获取顶点
     * @param index
     * @param out
     */
    vertex(index,out){
        out.x=this.vertices[index*2];
        out.y=this.vertices[index*2+1];
    }

    /**
     * 设置边序列长度
     * @param length
     */
    set lCount(length){
        this.lines=new Uint16Array(length);
    }

    /**
     * 重设
     */
    reset(){
        this.vertices=null;
        this.lines=null;
        this.maxX=Number.NEGATIVE_INFINITY;
        this.maxY=Number.NEGATIVE_INFINITY;
        this.minX=Number.POSITIVE_INFINITY;
        this.minY=Number.POSITIVE_INFINITY;
    }

    /**
     * 释放
     */
    dispose(){
        this.vertices=null;
        this.lines=null;
        this.maxX=null;
        this.maxY=null;
        this.minX=null;
        this.minY=null;
    }
}

/**
 * 选取厚度线的配置(HardLine)
 */
export default class SelectHardLineConfig extends SelectConfig{
    constructor(values){
        console.warn('this class is deprecated now !');
        super(values);
    }

    /**
     * 配置类型
     * @returns {string}
     */
    get type(){
        return 'SelectHardLineConfig';
    }

    /**
     * 射线检测（线）阈值
     * @param num
     */
    set threshold(num){
        this._rayCaster.params.Line.threshold=num;
    }

    checkType(object){
        return object instanceof HardLine;
    }
    compare(a, b) {
        return a.uuid===b.uuid;
    }
    intersectRect(object,pointer1,pointer2,camera,rect){
        if(!object.visible)return false;
        let box=this._tB0;
        GeometryUtils.make2DAABB(pointer1.x,pointer2.x,pointer1.y,pointer2.y,box,false);
        box.min.z=-0.1;
        box.max.z=0.1;
        return this.checkProjectionGeometry(object,box,camera,rect);
    }
    checkProjectionGeometry(object,box,camera,rect){
        this._projectGeometry(object,this._projGeometry,camera,rect);
        let objectRect=this._tB1;
        GeometryUtils.make2DAABB(this._projGeometry.minX,this._projGeometry.maxX,this._projGeometry.minY,this._projGeometry.maxY,objectRect,true);
        objectRect.min.z=-0.1;
        objectRect.max.z=0.1;
        if (!box.intersectsBox(objectRect)){
            return false;
        }
        for (let i=0;i<this._projGeometry.vertices.length/2;i++) {
            this._projGeometry.vertex(i,this._tV1);
            if (box.containsPoint(this._tV1)){
                return true;
            }
        }
        for (let j =0;j<this._projGeometry.lines.length/2;j++) {
            this._projGeometry.vertex(this._projGeometry.lines[j*2],this._tV0);
            this._projGeometry.vertex(this._projGeometry.lines[j*2+1],this._tV1);
            if (GeometryUtils.lineIntersectsBox(this._tV0,this._tV1,box,2,true)){
                return true;
            }
        }
        return false;
    }
    intersectPointer(object,pointer,info,camera,rect){
        if(!object.visible)return false;
        let x = (pointer.x - rect.left) / rect.width;
        let y = (pointer.y - rect.top) / rect.height;
        this._tV0.set(x * 2 - 1, 1 - y * 2,0);
        this._rayCaster.setFromCamera(this._tV0, camera);
        return this._rayCaster.intersectObject(object, false,info);
    }
    dispose() {
        super.dispose();
        this._projGeometry.dispose();
        this._tV0=null;
        this._tV1=null;
        this._tB0=null;
        this._tB1=null;
        this._tV3=null;
        this._projGeometry=null;
        this._rayCaster=null;
    }

    _initVariable() {
        super._initVariable();
        this._tV0=new THREE.Vector3();
        this._tV1=new THREE.Vector3();
        this._tB0=new THREE.Box3();
        this._tB1=new THREE.Box3();
        this._tV3=new THREE.Vector3();
        this._projGeometry=new SelectGeometry();
        this._rayCaster=new THREE.Raycaster();
        this._rayCaster.params.Line.threshold=this._values.threshold||0.1;
    }
    _projectGeometry(object,out,camera,rect) {
        out.reset();
        let trsMatrix = object.matrixWorld;
        let halfWidth = rect.width / 2;
        let halfHeight = rect.height / 2;
        camera.updateMatrixWorld();

        out.vCount=object.vertices.length*2;
        for (let i = 0; i < object.vertices.length; i++) {
            this._tV3.copy(object.vertices[i]);
            this._tV3.applyMatrix4(trsMatrix).project(camera);
            let x = (this._tV3.x * halfWidth) + halfWidth + rect.left;
            let y = -(this._tV3.y * halfHeight) + halfHeight + rect.top;

            if (out.maxX < x) out.maxX = x;
            if (out.maxY < y) out.maxY = y;
            if (out.minX > x) out.minX = x;
            if (out.minY > y) out.minY = y;

            out.vertices[i * 2] = x;
            out.vertices[i * 2 + 1] = y;
        }

        let vl = object.vertices.length;
        out.lCount = (vl - 1) * 2;
        for (let i = 0; i < vl - 1; i++) {
            out.lines[i*2] = i;
            out.lines[i * 2 + 1] = i + 1;
        }
    }
}